package com.lightsh.test;

import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.World;

import com.lightsh.configure.Configure;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;

public class PerformanceTester {
    
	/** 计算即时帧速度时，使用最近的fpsAverageCount帧来求平均值 */
	private final static int FPS_AVERAGE_COUNT = 100;
	
	/** 预期的帧速度,该值只有在初始化时用来模拟即时帧速度 */
    private static final int TARGET_FPS = (int) Configure.PHYSICS_TIME_STEP;
	
	/** 记录最近fpsAverageCount帧的时间 */
	private long[] nanos;
	/** 性能测试的开始时间 */
	private long nanoStart;

	/** 一共跑了的总帧数 */
	private long frameCount = 0;
    
    
    /** 即时帧数 */
    public float averagedFPS = 0.0f;
    
    /** 总的平均帧数 */
    public float totalFPS = 0.0f;
    
    private boolean mbInit = false;
    
    private Paint mPaint;
    
    /**
     * 释放的内存
     */
    private float mFreeMemory;
    
    public PerformanceTester(){
    }

    private void init(){
    	frameCount = 0;
    	nanos = new long[FPS_AVERAGE_COUNT];		
		// 我们假设开始时，之前的fpsAverageCount个帧速度是以我们的预期速度来完成的。
		long nanosPerFrameGuess = (long) (1000000000.0 / TARGET_FPS);
		nanos[FPS_AVERAGE_COUNT - 1] = System.nanoTime();
		for (int i = FPS_AVERAGE_COUNT - 2; i >= 0; --i) {
			nanos[i] = nanos[i + 1] - nanosPerFrameGuess;
		}
		nanoStart = System.nanoTime();
		mbInit = true;
		
		mFreeMemory = Runtime.getRuntime().freeMemory();
		Vec2.watchCreations = true;
    }
    
    /**
     * 计算下一个帧
     * <br/>调用该方法来触发一个帧的产生和计算
     */
    public void nextFPS() {
    	
    	if(!mbInit){
    		init();
    	}
    	
    	// 将fpsAverageCount之前的那一个frame时间移除
		for (int i = 0; i < FPS_AVERAGE_COUNT - 1; ++i) {
			nanos[i] = nanos[i + 1];
		}
		nanos[FPS_AVERAGE_COUNT - 1] = System.nanoTime();
		
		
		// 计算平均帧速度
		averagedFPS = (float) ((FPS_AVERAGE_COUNT - 1) * 1000000000.0 / (nanos[FPS_AVERAGE_COUNT - 1] - nanos[0]));
		
		// 计算总的帧速度
		++frameCount;
		totalFPS = (float) (frameCount * 1000000000 / (1.0 * (System.nanoTime() - nanoStart)));
		
    }

    private static final String STR_AVERAGE_TIP = "即时 FPS(" + FPS_AVERAGE_COUNT + "frames) = ";
    private static final String STR_TOTAL_TIP =   "所有帧平均 FPS = ";
    private int mCurrentY;
    /**
     * 绘制性能信息, 当world传入null时不绘制与box2d相关的信息
     */
    public void drawPerformanceInfo(Canvas canvas, World world){
    	if(mPaint == null){
    		mPaint = new Paint();
    		mPaint.setStyle(Paint.Style.FILL);
    		mPaint.setColor(Color.WHITE);
    		mPaint.setTextSize(25f);
    	}
    	
    	mCurrentY = 30;
    	if(world != null){
    		canvas.drawText("bodies/contacts/joints = " + world.getBodyCount() + "/" + world.getContactCount() + "/" + world.getJointCount(), 30, mCurrentY, mPaint);    	
        	mCurrentY += 30;
    	}
    	
    	long memTotal = Runtime.getRuntime().totalMemory();
		mFreeMemory = (mFreeMemory * .9f + .1f * Runtime.getRuntime().freeMemory());
    	canvas.drawText("总可用内存 = " + memTotal, 30, mCurrentY, mPaint);    	
    	mCurrentY += 30;
    	
    	canvas.drawText("平均空闲内存 = " + (long)mFreeMemory, 30, mCurrentY, mPaint);
    	mCurrentY += 30;
    	
    	if(world != null){
    		canvas.drawText("Vec2 creations/frame = " + Vec2.creationCount, 30, mCurrentY, mPaint);
    		// 这里重置它，这个计数器只会不断增加，而不会在析构时减少
        	Vec2.creationCount = 0;
        	
        	mCurrentY += 30;
    	}
    	
    	canvas.drawText(STR_AVERAGE_TIP + averagedFPS, 30, mCurrentY, mPaint);
    	mCurrentY += 30;
    	canvas.drawText(STR_TOTAL_TIP + averagedFPS, 30, mCurrentY, mPaint);
    	
    }
    
    /**
     * 重置测试的数据
     * <br/>注意，只有在下一个{@link #nextFPS()}调用时，数据才会真正被重置
     */
    public void reset(){
    	mbInit = false;
    }
}
